//
//  ZGAudioRecorder.swift
//  ZhangGuang
//
//  Created by 叁拾叁 on 2020/8/5.
//  Copyright © 2020 叁拾叁. All rights reserved.
//

import UIKit
import AVFoundation

protocol ZGAudioRecorderProtocol: class {// 将protocol限制在class内 这样才能使用weak，因为swift大都是struct类型，另一种方法是加@objc
    
    func getVoiceNum(num: Int)
    
}

class ZGAudioRecorder: NSObject {

    var recorder: AVAudioRecorder!
    var levelTimer: Timer!
    var getVoiceNumClosure: ((Int) -> Void)?
    var delegate: ZGAudioRecorderProtocol!
    
    func startRecord() {
       
        let audioSession: AVAudioSession = AVAudioSession.sharedInstance()
        
        do {
            //设置这个，可以修复录音只录一遍的问题
            try audioSession.setCategory(.playAndRecord)
            //设置这个，可以增加录音音量
            try audioSession.overrideOutputAudioPort(.speaker)
             //设置这个，配置生效
            try audioSession.setActive(true)
        } catch let error {
            debugPrint("Couldn't force audio to speaker: \(error)")
        }
        
        /* 不需要保存录音文件 */
        let filePath: String = NSHomeDirectory() + "/Documents/" + "record" + ".wav"
        let url: URL = URL.init(string: filePath)!
        
        let settings: [String: AnyObject] = [
            // 编码格式
            AVFormatIDKey: NSNumber(value: Int32(kAudioFormatLinearPCM)),
            // 采样率
            AVSampleRateKey: NSNumber(value: 11025.0),
            // 通道数
            AVNumberOfChannelsKey: NSNumber(value: 2),
            // 录音质量
            AVEncoderAudioQualityKey: NSNumber(value: Int32(AVAudioQuality.min.rawValue))
        ]
        
        do {
            recorder = try AVAudioRecorder(url: url, settings: settings)
        } catch {
            print(error)
        }
        if recorder != nil {
            recorder.prepareToRecord()
            recorder.isMeteringEnabled = true
            recorder.record()
            levelTimer = Timer.scheduledTimer(timeInterval: 0.3, target: self, selector: #selector(levelTimerCallback), userInfo: nil, repeats: true)
        }
        
    }
    
    func stopRecord() {
        recorder.stop()
        levelTimer.invalidate()
    }
    
    @objc func levelTimerCallback(timer: Timer) {
        
        recorder.updateMeters()
        var level: Float = 0.0              // The linear 0.0 .. 1.0 value we need.
        let minDecibels: Float = -60.0      // use -80db Or use -60dB, which I measured in a silent room.
        let decibels: Float = recorder.averagePower(forChannel: 0)
        if decibels < minDecibels {
            level = 0.0
        } else if decibels >= 0.0 {
            level = 1.0
        } else {
            let root: Float = 5.0           //modified level from 2.0 to 5.0 is neast to real test
            let minAmp: Float = powf(10.0, 0.05 * minDecibels)
            let inverseAmpRange: Float = 1.0 / (1.0 - minAmp)
            let amp: Float = powf(10.0, 0.05 * decibels)
            let adjAmp: Float = (amp - minAmp) * inverseAmpRange
            
            level = powf(adjAmp, 1.0 / root)
        }
        /* level 范围[0 ~ 1], 转为[0 ~120] 之间 */
        DispatchQueue.main.async {
            print("voice updated: \(level * 5)")
            self.delegate.getVoiceNum(num: Int(level * 5))
        }
    }
}
